package com.huanmeiqi.forkjoin.service;

import com.huanmeiqi.forkjoin.vo.Peach;
import com.huanmeiqi.forkjoin.vo.PeachFactory;
import org.junit.jupiter.api.Test;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * @author cq.Wang
 * @date 2018/8/7 17:34
 * @description
 */
public class MTest {

    class PickPeachTask extends RecursiveTask<Integer> {
        /**
         * 阈值。将大数组按100的长度分成小数组
         */
        private final int THRESHOLD = 200;

        /**
         * 存放蟠桃的大数组
         */
        private Peach[] array;

        private int fromIndex;

        private int toIndex;

        private MonkeyKing wuKong;

        public PickPeachTask(Peach[] array, int fromIndex, int toIndex, MonkeyKing wuKong) {
            this.array = array;
            this.fromIndex = fromIndex;
            this.toIndex = toIndex;
            this.wuKong = wuKong;
        }

        @Override
        protected Integer compute() {

            if ((toIndex - fromIndex) < THRESHOLD) {
                int count = 0;
                // 已经是小任务
                for (int i = fromIndex; i < toIndex; i++) {
                    if (wuKong.pickPeach(array, i)) {
                        wuKong.putBag(array, i);
                        count++;
                    }
                }
                return count;
            } else {
                System.out.println(Thread.currentThread().getName() + "切分小任务");
                int middleIndex = (toIndex + fromIndex) / 2;
                PickPeachTask leftTask = new PickPeachTask(array, fromIndex, middleIndex, wuKong);
                PickPeachTask rightTask = new PickPeachTask(array, middleIndex, toIndex, wuKong);
                // 执行子任务
                invokeAll(leftTask, rightTask);
                return leftTask.join() + rightTask.join();
            }
        }
    }

    /**
     * 不使用fork/join
     */
    @Test
    public void test01() {
        PeachFactory factory = new PeachFactory();
        Peach[] array = factory.makeArray(10000);
        MonkeyKing wuKong = new MonkeyKing();

        long start = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 10000; i++) {
            if (wuKong.pickPeach(array, i)) {
                wuKong.putBag(array, i);
                count++;
            }
        }

        System.out.println("摘桃子耗时->" + (System.currentTimeMillis() - start) + "ms;共摘了->" + count + "个");

    }

    /**
     * 使用fork/join框架。显然快多了
     */
    @Test
    public void test02() {
        // 最多 0x7fff(十六进制) = 32767(十进制)个线程，默认取Runtime.getRuntime().availableProcessors()
        ForkJoinPool pool = new ForkJoinPool(43);

        PeachFactory factory = new PeachFactory();
        Peach[] array = factory.makeArray(10000);
        MonkeyKing wuKong = new MonkeyKing();

        long start = System.currentTimeMillis();
        PickPeachTask peachTask = new PickPeachTask(array, 0, array.length - 1, wuKong);
        pool.invoke(peachTask);
        System.out.println("摘桃子耗时->" + (System.currentTimeMillis() - start) + "ms;共摘了->" + peachTask.join() + "个");
    }
}
